package net.groupme.model.rdf;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hp.hpl.jena.vocabulary.DC;
import com.hp.hpl.jena.vocabulary.XSD;

import net.groupme.controller.model.ImageSearchResult;
import net.groupme.controller.model.LocationSearchResult;
import net.groupme.controller.model.RssSearchResult;
import net.groupme.controller.model.SearchResult;
import net.groupme.exceptions.IDNotFoundException;
import net.groupme.exceptions.InsertFailedException;
import net.groupme.model.Resource;

/**
 * 
 * created on 04.07.2007
 * 
 * This class extracts the Metadata out of an SearchResult.
 * 
 * @author Mischa Frank, <a href="mailto:code@planetfrank.net">code@planetfrank.net</a>
 * @author Fabian Abel, <a href="mailto:abel@l3s.de">abel@l3s.de</a>
 * 
 * @author last edited by: $Author: fabian $
 * 
 * @version $Revision: 1.7 $ $Date: 2007-12-04 15:15:45 $
 */
public class MetadataUtility {
	/** Logger for this class and subclasses */
	protected static final Log logger = LogFactory.getLog(MetadataUtility.class);
	/* TODO: move to vocabulary class of Location/Map-Search-Engine */
	private static final String WSG84_LATITUDE = "http://www.w3.org/2003/01/geo/wgs84_pos#lat";
	private static final String WSG84_LONGITUDE = "http://www.w3.org/2003/01/geo/wgs84_pos#long";
	
	/**
	 * This method extracts the metadata of a SearchResult, puts them into
	 * {@link Statement} and returns them as an array.
	 * @param searchResult the object where the metadata should be extracted from
	 * @param resource the {@link Resource} the Metadata belongs to
	 * @return true if successful, otherwise false
	 */
	public static final boolean extractAndAdd(SearchResult searchResult, Resource resource){
		extractAndAddNormalResourceMetadata(searchResult, resource);
		if (searchResult instanceof ImageSearchResult){
			try {
				extractAndAddTypicalImageMetadata((ImageSearchResult)searchResult, resource);
			} catch (IDNotFoundException e) {
				logger.error("given resource could not be resolved ", e);
				return false;
			} catch (InsertFailedException e) {
				logger.error("failed to add the statement to the resource", e);
				return false;
			}
		}
		if (searchResult instanceof RssSearchResult){
			try {
				extractAndAddTypicalRssMetadata((RssSearchResult)searchResult, resource);
			} catch (IDNotFoundException e) {
				logger.error("given resource could not be resolved ", e);
				return false;
			} catch (InsertFailedException e) {
				logger.error("failed to add the statement to the resource", e);
				return false;
			}
		}
		logger.info("Type of Search result to add: " + searchResult.getClass().toString());
		if (searchResult instanceof LocationSearchResult){
			try {
				extractAndAddTypicalLocationMetadata((LocationSearchResult)searchResult, resource);
			} catch (IDNotFoundException e) {
				logger.error("given resource could not be resolved ", e);
				return false;
			} catch (InsertFailedException e) {
				logger.error("failed to add the statement to the resource", e);
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Extracts and adds typical metadata properties of a normal web resource.
	 * <strong>Note:</strong> At the moment this method does nothing, because all
	 * common metadata properties are deduced from the properties of the class
	 * {@link Resource}. 
	 * @param searchResult the search result
	 * @param resource the resource that should be extended with metadata
	 */
	private static final void extractAndAddNormalResourceMetadata(SearchResult searchResult, Resource resource){
		//wird momentan noch nicht gebraucht...
	}
	
	/**
	 * Extracts and adds metadata properties which are typical for an image/photo.
	 * 
	 * @param searchResult the search result
	 * @param resource the resource that should be extended with metadata
	 * @throws InsertFailedException thrown if it failed to add the statement to the resource
	 * @throws IDNotFoundException  thrown if given resource could not be resolved 
	 */
	private static final void extractAndAddTypicalImageMetadata(ImageSearchResult searchResult, Resource resource) throws IDNotFoundException, InsertFailedException{
		if(searchResult.getDateCreated() != null && !"".equals(searchResult.getDateCreated())){
			resource.addStatement(DC.date.getURI(), searchResult.getDateCreated(), XSD.date.getURI());
		}
		if(searchResult.getOwner() != null && !"".equals(searchResult.getOwner())){
			resource.addStatement(DC.contributor.getURI(), searchResult.getOwner(), XSD.xstring.getURI());
		}
		if(searchResult.getUrlOfThumbnail() != null && !"".equals(searchResult.getUrlOfThumbnail())){
			resource.addStatement(DC.relation.getURI(), searchResult.getUrlOfThumbnail(), XSD.anyURI.getURI());
		}
		if(searchResult.getPublisher() != null && !"".equals(searchResult.getPublisher())){
			resource.addStatement(DC.publisher.getURI(), searchResult.getPublisher(), XSD.anyURI.getURI());
		}
		if(searchResult.getFlickrTags() != null){
			for(Object tag: searchResult.getFlickrTags()){
				resource.addStatement(DC.subject.getURI(), tag.toString(), XSD.xstring.getURI());
			}
		}
	}
	
	/**
	 * Extracts and adds metadata properties which are typical for an rss feed.
	 * 
	 * @param searchResult the search result
	 * @param resource the resource that should be extended with metadata
	 * @throws InsertFailedException thrown if it failed to add the statement to the resource
	 * @throws IDNotFoundException  thrown if given resource could not be resolved 
	 */
	private static final void extractAndAddTypicalRssMetadata(RssSearchResult searchResult, Resource resource) throws IDNotFoundException, InsertFailedException{
		if(searchResult.getPubDate() != null && !"".equals(searchResult.getPubDate())){
			resource.addStatement(DC.date.getURI(), searchResult.getPubDate().toString(), XSD.date.getURI());
		}
		if(searchResult.getLastUpdatet() != null && !"".equals(searchResult.getLastUpdatet())){
			resource.addStatement(DC.date.getURI(), searchResult.getLastUpdatet().toString(), XSD.date.getURI());
		}
		if(searchResult.getLanguage() != null && !"".equals(searchResult.getLanguage())){
			resource.addStatement(DC.language.getURI(), searchResult.getLanguage(), XSD.xstring.getURI());
		}
		if(searchResult.getPublisher() != null && !"".equals(searchResult.getPublisher())){
			resource.addStatement(DC.publisher.getURI(), searchResult.getPublisher().toString(), XSD.xstring.getURI());
		}
		if(searchResult.getImageURL() != null && !"".equals(searchResult.getImageURL())){
			resource.addStatement(DC.relation.getURI(), searchResult.getImageURL().toString(), XSD.anyURI.getURI());
		}
		if(searchResult.getCopyright() != null && !"".equals(searchResult.getCopyright())){
			resource.addStatement(DC.rights.getURI(), searchResult.getCopyright().toString(), XSD.xstring.getURI());
		}
		if(searchResult.getLocation() != null && !"".equals(searchResult.getLocation())){
			resource.addStatement(DC.relation.getURI(), searchResult.getLocation().toString(), XSD.anyURI.getURI());
		}
		if(searchResult.getSite() != null && !"".equals(searchResult.getSite())){
			resource.addStatement(DC.relation.getURI(), searchResult.getSite().toString(), XSD.anyURI.getURI());
		}
	}
	

	/**
	 * Extracts and adds metadata properties which are typical for an rss feed.
	 * 
	 * @param searchResult the search result
	 * @param resource the resource that should be extended with metadata
	 * @throws InsertFailedException thrown if it failed to add the statement to the resource
	 * @throws IDNotFoundException  thrown if given resource could not be resolved 
	 */
	private static final void extractAndAddTypicalLocationMetadata(LocationSearchResult searchResult, Resource resource) throws IDNotFoundException, InsertFailedException{
		if(searchResult.getLatitude() != null && !"".equals(searchResult.getLatitude())){
			resource.addStatement(WSG84_LATITUDE, searchResult.getLatitude(), XSD.anyURI.getURI());
		}
		if(searchResult.getLongitude() != null && !"".equals(searchResult.getLongitude())){
			resource.addStatement(WSG84_LONGITUDE, searchResult.getLongitude(), XSD.anyURI.getURI());
		}
		
	}
}
